// 版权所有 Epic Games, Inc. 保留所有权利。

#pragma once

#include "ReplicationGraph.h"
#include "LyraReplicationGraphTypes.h"
#include "LyraReplicationGraph.generated.h"

class AGameplayDebuggerCategoryReplicator;

DECLARE_LOG_CATEGORY_EXTERN(LogLyraRepGraph, Display, All); // 声明复制图日志类别

/** Lyra 复制图实现。有关其他说明，请参阅 LyraReplicationGraph.cpp！ */
UCLASS(transient, config=Engine)
class ULyraReplicationGraph : public UReplicationGraph
{
	GENERATED_BODY()

public:
	ULyraReplicationGraph(); // 构造函数

	virtual void ResetGameWorldState() override; // 重置游戏世界状态

	virtual void InitGlobalActorClassSettings() override; // 初始化全局角色类设置
	virtual void InitGlobalGraphNodes() override; // 初始化全局图节点
	virtual void InitConnectionGraphNodes(UNetReplicationGraphConnection* RepGraphConnection) override; // 初始化连接图节点
	virtual void RouteAddNetworkActorToNodes(const FNewReplicatedActorInfo& ActorInfo, FGlobalActorReplicationInfo& GlobalInfo) override; // 路由添加网络角色到节点
	virtual void RouteRemoveNetworkActorToNodes(const FNewReplicatedActorInfo& ActorInfo) override; // 路由移除网络角色到节点

	UPROPERTY()
	TArray<TObjectPtr<UClass>>	AlwaysRelevantClasses; // 始终相关类数组
	
	UPROPERTY()
	TObjectPtr<UReplicationGraphNode_GridSpatialization2D> GridNode; // 网格空间化节点

	UPROPERTY()
	TObjectPtr<UReplicationGraphNode_ActorList> AlwaysRelevantNode; // 始终相关节点

	TMap<FName, FActorRepListRefView> AlwaysRelevantStreamingLevelActors; // 始终相关流关卡角色映射

#if WITH_GAMEPLAY_DEBUGGER
	void OnGameplayDebuggerOwnerChange(AGameplayDebuggerCategoryReplicator* Debugger, APlayerController* OldOwner); // 游戏调试器所有者变更处理
#endif

	void PrintRepNodePolicies(); // 打印复制节点策略

private:
	void AddClassRepInfo(UClass* Class, EClassRepNodeMapping Mapping); // 添加类复制信息
	void RegisterClassRepNodeMapping(UClass* Class); // 注册类复制节点映射
	EClassRepNodeMapping GetClassNodeMapping(UClass* Class) const; // 获取类节点映射

	void RegisterClassReplicationInfo(UClass* Class); // 注册类复制信息
	bool ConditionalInitClassReplicationInfo(UClass* Class, FClassReplicationInfo& ClassInfo); // 条件初始化类复制信息
	void InitClassReplicationInfo(FClassReplicationInfo& Info, UClass* Class, bool Spatialize) const; // 初始化类复制信息

	EClassRepNodeMapping GetMappingPolicy(UClass* Class); // 获取映射策略

	bool IsSpatialized(EClassRepNodeMapping Mapping) const { return Mapping >= EClassRepNodeMapping::Spatialize_Static; } // 检查是否空间化

	TClassMap<EClassRepNodeMapping> ClassRepNodePolicies; // 类复制节点策略映射

	/** 在 ULyraReplicationGraph::InitGlobalActorClassSettings 中通过代码显式设置其复制设置的类 */
	TArray<UClass*> ExplicitlySetClasses; // 显式设置类数组
};

UCLASS()
class ULyraReplicationGraphNode_AlwaysRelevant_ForConnection : public UReplicationGraphNode_AlwaysRelevant_ForConnection
{
	GENERATED_BODY()

public:
	virtual void NotifyAddNetworkActor(const FNewReplicatedActorInfo& Actor) override { } // 通知添加网络角色
	virtual bool NotifyRemoveNetworkActor(const FNewReplicatedActorInfo& ActorInfo, bool bWarnIfNotFound=true) override { return false; } // 通知移除网络角色
	virtual void NotifyResetAllNetworkActors() override { } // 通知重置所有网络角色

	virtual void GatherActorListsForConnection(const FConnectionGatherActorListParameters& Params) override; // 为连接收集角色列表

	virtual void LogNode(FReplicationGraphDebugInfo& DebugInfo, const FString& NodeName) const override; // 记录节点

	void OnClientLevelVisibilityAdd(FName LevelName, UWorld* StreamingWorld); // 客户端关卡可见性添加
	void OnClientLevelVisibilityRemove(FName LevelName); // 客户端关卡可见性移除

	void ResetGameWorldState(); // 重置游戏世界状态

#if WITH_GAMEPLAY_DEBUGGER
	AGameplayDebuggerCategoryReplicator* GameplayDebugger = nullptr; // 游戏调试器
#endif

private:
	TArray<FName, TInlineAllocator<64> > AlwaysRelevantStreamingLevelsNeedingReplication; // 需要复制的始终相关流关卡数组

	bool bInitializedPlayerState = false; // 玩家状态是否已初始化
};

/** 
	这是一个专门用于以频率限制方式处理PlayerState复制的节点。它跟踪所有玩家状态，但每帧只返回其中的一个子集给复制驱动程序。
	这是针对大量玩家连接数的优化，不是必需的要求。
*/
UCLASS()
class ULyraReplicationGraphNode_PlayerStateFrequencyLimiter : public UReplicationGraphNode
{
	GENERATED_BODY()

	ULyraReplicationGraphNode_PlayerStateFrequencyLimiter(); // 构造函数

	virtual void NotifyAddNetworkActor(const FNewReplicatedActorInfo& Actor) override { } // 通知添加网络角色
	virtual bool NotifyRemoveNetworkActor(const FNewReplicatedActorInfo& ActorInfo, bool bWarnIfNotFound=true) override { return false; } // 通知移除网络角色
	virtual bool NotifyActorRenamed(const FRenamedReplicatedActorInfo& Actor, bool bWarnIfNotFound=true) override { return false; } // 通知角色重命名

	virtual void GatherActorListsForConnection(const FConnectionGatherActorListParameters& Params) override; // 为连接收集角色列表

	virtual void PrepareForReplication() override; // 准备复制

	virtual void LogNode(FReplicationGraphDebugInfo& DebugInfo, const FString& NodeName) const override; // 记录节点

	/** 我们每帧想要返回给复制驱动程序的角色数量。不会抑制ForceNetUpdate。 */
	int32 TargetActorsPerFrame = 2; // 每帧目标角色数

private:
	
	TArray<FActorRepListRefView> ReplicationActorLists; // 复制角色列表数组
	FActorRepListRefView ForceNetUpdateReplicationActorList; // 强制网络更新复制角色列表
};